package com.xuyu.ddd.aggregate.core.field;

import java.io.Serializable;
import java.util.Objects;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * 懒加载封装类，用于削减复杂对象的构造时间、定制字段是否加载。
 * @param <T>
 */
public class Lazy<T> implements Supplier<T>, Serializable {

    public transient Supplier<? extends T> supplier;

    public T value;

    public Lazy() {}
    private Lazy(Supplier<? extends T> supplier) {
        this.supplier = supplier;
    }

    private Lazy(T value) {
        this.value = value;
    }

    public static <T> Lazy<T> of(Supplier<? extends T> supplier) {
        return new Lazy<>(supplier);
    }

    public static <T> Lazy<T> of(T value) {
        return new Lazy<>(value);
    }

    /**
     * 正常业务处理过程中获取字段的值
     * @return 返回结果
     */
    public T get() {
        if (value == null) {
            synchronized (this) {
                //第一次加载
                value = supplier.get();
            }
        }
        return value;
    }


    /**
     * 直接获取当前的值，一般情况下仅用于持久化的时候，用来判断是否进行更改了
     * @return 返回value
     */
    public T getCurrentValue() {
        return value;
    }

    public <S> Lazy<S> map(Function<? super T, ? extends S> function) {
        return Lazy.of(() -> function.apply(get()));
    }

    public <S> Lazy<S> flatMap(Function<? super T, Lazy<? extends S>> function) {
        return Lazy.of(() -> function.apply(get()).get());
    }


    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Lazy<?> lazy = (Lazy<?>) o;
        return Objects.equals(value, lazy.value);
    }

    @Override
    public int hashCode() {
        return Objects.hash(value);
    }
}
